<template>
    <div :class="[
        type === 'textarea' ? 'el-textarea' : 'el-input',
        this.size ? 'el-input--' + this.size : '',
        {
            'is-disabled': disabled,
            'el-input--prefix': $slots.prefix || prefixIcon,
            'el-input-group': $slots.prepend || $slots.append,
            'el-input-group--append': $slots.append,
            'el-input-group--prepend': $slots.prepend,
            'el-input--suffix': $slots.suffix || suffixIcon || clearable || showPassword
        }
        ]"
        @mouseenter="hovering = true"
        @mouseleave="hovering = false"
    >
        <template v-if="type !== 'textarea'">
            <!-- 前置元素 -->
            <div class="el-input-group__prepend" v-if="$slots.prepend">
                <slot name="prepend"></slot>
            </div>
            <input
                ref="input"
                class="el-input__inner"        
                v-bind="$attrs"
                :type="showPassword ? (passwordVisible ? 'text': 'password') : type"
                :value="value"
                :disabled="disabled"
                @input="$emit('input', $event.target.value)"
                @focus="handleFocus"
                @blur="handleBlur"
                @change="$emit('change', $event.target.value)"
            />
            <!-- 前置内容 -->
            <span class="el-input__prefix" v-if="$slots.prefix || prefixIcon">
                <slot name="prefix"></slot>
                <i class="el-input__icon"
                v-if="prefixIcon"
                :class="prefixIcon">
                </i>
            </span>
            <!-- 后置内容 -->
            <span
                class="el-input__suffix"
                v-if="getSuffixVisible()">
                <template v-if="!showClear || !showPwdVisible || !isWordLimitVisible">
                    <slot name="suffix"></slot>
                    <i class="el-input__icon"
                    v-if="suffixIcon"
                    :class="suffixIcon">
                    </i>
                </template>
                <span class="el-input__suffix-inner">
                    <i v-if="showClear"
                        class="el-input__icon el-icon-circle-close el-input__clear"
                        @mousedown.prevent
                        @click="clear"
                    ></i>
                     <i v-if="showPwdVisible"
                        class="el-input__icon el-icon-view el-input__clear"
                        @click="handlePasswordVisible"
                    ></i>
                    <span v-if="isWordLimitVisible" class="el-input__count">
                        <span class="el-input__count-inner">
                        {{ textLength }}/{{ upperLimit }}
                        </span>
                    </span>
                </span>
            </span>
            <!-- 后置元素 -->
            <div class="el-input-group__append" v-if="$slots.append">
                <slot name="append"></slot>
            </div>
        </template>
        <textarea
            v-else
            ref="textarea"
            class="el-textarea__inner"
            v-bind="$attrs"
            :disabled="disabled"
            :style="textareaStyle"
            @input="$emit('input', $event.target.value)"
            @focus="handleFocus"
            @blur="handleBlur"
            @change="$emit('change', $event.target.value)"
            >
        </textarea>
        <span v-if="isWordLimitVisible && type === 'textarea'" class="el-input__count">{{ textLength }}/{{ upperLimit }}</span>
    </div>
</template>

<script>
import merge from '../../utils/merge';
import calcTextareaHeight from './calcTextareaHeight.js';

export default {
    name: 'ElInput',
    props: {
        value: [String, Number],
        disabled: Boolean,
        size: String,
        type: {
            type: String,
            default: 'text'
        },
        clearable: {
            type: Boolean,
            default: false
        },
        showPassword: {
            type: Boolean,
            default: false
        },
        suffixIcon: String,
        prefixIcon: String,
        resize: String,
        autosize: {
            type: [Boolean, Object],
            default: false
        },
        showWordLimit: {
            type: Boolean,
            default: false
        },
    },
     data() {
      return {
        hovering: false,
        focused: false,
        isComposing: false,
        passwordVisible: false,
        textareaCalcStyle: {},
      };
    },
    computed: {
        nativeInputValue() {
            return this.value === null || this.value === undefined ? '' : String(this.value);
        },
        showClear() {
            return this.clearable &&
            !this.disabled &&
            (this.focused || this.hovering) &&
            !!this.nativeInputValue;
        },
        showPwdVisible() {
            return this.showPassword &&
            (!!this.nativeInputValue || this.focused);
        },
        textareaStyle() {
            return merge({}, this.textareaCalcStyle, { resize: this.resize });
        },
        isWordLimitVisible() {
            return this.showWordLimit &&
            this.$attrs.maxlength &&
            (this.type === 'text' || this.type === 'textarea') &&
            !this.disabled &&
            !this.showPassword;
        },
        upperLimit() {
            return this.$attrs.maxlength;
        },
        textLength() {
            if (typeof this.value === 'number') {
            return String(this.value).length;
            }
            return (this.value || '').length;
        },
    },
    watch: {
        value() {
            this.$nextTick(this.resizeTextarea);
        },
        type() {
            this.$nextTick(this.resizeTextarea);
        }
    },
    methods: {
        handleFocus(event) {
            this.focused = true;
            this.$emit('focus', event);
        },
        handleBlur(event) {
            this.focused = false;
            this.$emit('blur', event);
        },
        handlePasswordVisible() {
            this.passwordVisible = !this.passwordVisible;
            this.focus();
        },
        clear() {
            this.$emit('input', '');
            this.$emit('change', '');
            this.$emit('clear');
        },

        focus() {
            this.getInput().focus();
            setTimeout(() => {
                this.getInput().setSelectionRange(-1,-1);
            });
        },
        blur() {
            this.getInput().blur();
        },
        
        resizeTextarea() {
            const { autosize, type } = this;
            if (type !== 'textarea') return;
            if (!autosize) {
                this.textareaCalcStyle = {
                    minHeight: calcTextareaHeight(this.$refs.textarea).minHeight
                };
                return;
            }
            const minRows = autosize.minRows;
            const maxRows = autosize.maxRows;
            this.textareaCalcStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
        },
        getSuffixVisible() {
            return this.$slots.suffix ||
                    this.suffixIcon || 
                    this.showClear || 
                    this.showPwdVisible ||
                    this.isWordLimitVisible
        },
        getInput() {
            return this.$refs.input || this.$refs.textarea;
        },
    },
    mounted() {
      this.resizeTextarea();
    },
  };
</script>